### **Chrome Extensions: Changes from Manifest V2 to V3**
Chrome **Manifest V3 (MV3)** introduced significant security, performance, and privacy improvements, but also removed some key features from **Manifest V2 (MV2)**.
Here’s a breakdown of what was **removed**, what was **added**, and what was **changed**:
---
## **🚫 Features Removed in Manifest V3**
### **1. Background Pages → Replaced with Service Workers**
- **MV2:** Extensions used **persistent background pages** (`background.html` or a background script).
- **MV3:** **Service workers** are now required instead.
- Service workers **only run when needed**, reducing resource usage.
- They **cannot use `setTimeout()` or long-running connections**.
- `chrome.runtime.getBackgroundPage()` is no longer available.
✅ **Alternative: Use event-driven service workers.**
```json
{
"background": {
"service_worker": "background.js"
}
}
```
---
### **2. `chrome.browserAction` & `chrome.pageAction` → Merged into `chrome.action`**
- **MV2:** Used `browserAction` (for global actions) and `pageAction` (for per-tab actions).
- **MV3:** Both are merged into `chrome.action`.
✅ **Example:**
```json
{
"action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}
```
---
### **3. `chrome.extension.getBackgroundPage()` Removed**
- **MV2:** Allowed retrieving the background page.
- **MV3:** Not available due to service workers.
✅ **Alternative:** Use `chrome.runtime.sendMessage()`.
---
### **4. `content_security_policy` Changes**
- **MV2:** Allowed `unsafe-inline` in `style-src` and `script-src`.
- **MV3:** **Removes `'unsafe-inline'` and `'unsafe-eval'`**.
- No inline scripts (``)... because it's no longer covered under unsafe-eval and unsafe inline and will error in console. Use js file instead.
- No inline event handlers (`onclick=""` won't work).
- No `eval()` or `setTimeout("code", delay)`.
- Reworded: unsafe-inline no longer supported in v3
```
"content_security_policy": {
"extension_pages": style-src 'self' 'unsafe-inline';"
```
- This policy in v2 disallows external css files and allows inline style `
{
console.log("Checking for updates...");
});
```
---
### **2. `chrome.scripting` API for Content Scripts**
- **MV2:** Content scripts were managed via `tabs.executeScript()`.
- **MV3:** New `chrome.scripting.executeScript()` API.
✅ **Example: Injecting a script dynamically**
```javascript
chrome.scripting.executeScript({
target: { tabId: someTabId },
files: ["content-script.js"]
});
```
---
### **3. Separation of API and Hosting Permissions**
In Manifest V2, everything was lumped together under `permissions`, which led to **overly broad permissions**. V3 splits them to encourage **least privilege**:
- `permissions`: Core Chrome features
- `host_permissions`: Access to specific sites
Chrome can now also **request host permissions at runtime** (via the **optional permissions** model), which gives users more control.
Example:
```
"permissions": [
"storage",
"tabs",
"scripting",
"notifications"
],
"host_permissions": [
"https://*.example.com/*",
"*://*.google.com/*"
]
```
---
### 4. Improved Security & Permissions Model**
- Extensions must **declare all host permissions explicitly** in `manifest.json` (`activeTab` no longer allows access to all sites).
- **Optional permissions** can now be requested dynamically.
✅ **Example: Requesting host permissions at runtime**
```javascript
chrome.permissions.request({
permissions: ["tabs"],
origins: ["https://example.com/"]
});
```
---
### **5. New `declarativeNetRequest` API**
- **MV3's replacement for `webRequest` API**.
- Predefined rules in `rules.json` control network requests.
- Less flexible but more performant.
✅ **Example: Blocking ads**
```json
[
{
"id": 1,
"priority": 1,
"action": { "type": "block" },
"condition": { "urlFilter": "ads.example.com", "resourceTypes": ["script"] }
}
]
```
---
### **6. New Host Permission Model**
- In **MV2**, declaring `"host_permissions"` granted immediate access.
- In **MV3**, `"host_permissions"` must be **explicitly requested at runtime**.
✅ **Example:**
```json
{
"host_permissions": ["https://example.com/"]
}
```
---
### **7. All scripts must be local in Manifest V3**
**All JavaScript must be included in the extension package itself.**
- ❌ Wildcards (`*`) or remote domains are **not allowed** for `script-src` in Chrome Extension CSP.
- ✅ `'self'` is permitted.
Wildcards like `*` **were allowed** in `script-src` and `style-src`, in V2, although **not recommended**. In V3, it’s completely not allowed.
---
### **8. `offscreen` API for Hidden Background Work**
- Allows running tasks like audio playback without a visible tab.
- Used when service workers **cannot handle background tasks**.
✅ **Example: Create an offscreen document**
```javascript
chrome.offscreen.createDocument({
url: "offscreen.html",
reasons: ["AUDIO_PLAYBACK"],
justification: "Playing background music"
});
```
---
## **📌 Summary of Key Differences**
| Feature | Manifest V2 | Manifest V3 |
| ---------------------------------------- | ---------------------------------------- | -------------------------------------------------------- |
| **Background Scripts** | Persistent `background.js` | **Service workers** (non-persistent) |
| **Long-running Background Tasks** | Persistent pages | **Use `offscreen` API** or `alarms` |
| **`browserAction` / `pageAction`** | Two separate APIs | ✅ **Merged into `chrome.action`** |
| **`chrome.runtime.getBackgroundPage()`** | ✅ Available | 🚫 **Removed** (use messaging instead) |
| **Inline Scripts & Styles** | ✅ Allowed (`unsafe-inline`) | 🚫 **Blocked** (Use external files only) |
| **Blocking `webRequest` API** | ✅ Allowed | 🚫 **Replaced with `declarativeNetRequest`** |
| **`chrome.runtime.onSuspend`** | ✅ Available | 🚫 **Removed** (service workers suspend automatically) |
| **Executing Scripts** | `tabs.executeScript()` | 🚀 **Use `chrome.scripting.executeScript()`** |
| **Split Permissions Model** | All in `permissions` | ✅ **Split into `permissions` + `host_permissions`** |
| **Permissions Model** | Implicit host permissions | 🚫 **Must be declared explicitly** |
| **Event Handling** | Inline handlers (`onclick=""`) allowed | 🚫 **Use `addEventListener()` instead** |
| **All Scripts Must Be Local** | Remote scripts allowed (not recommended) | 🚫 **Only local scripts allowed** |
| **`offscreen` API** | ❌ Not available | ✅ **New API for hidden background tasks** |
| **Dynamic Host Permissions** | ❌ Not supported | ✅ **Can request at runtime via `permissions.request()`** |
✅ **Pros of Manifest V3**
- **Better performance** (less memory usage).
- **Stronger security** (no inline scripts, fewer attack vectors).
- **More efficient request handling** (`declarativeNetRequest`).
- **More granular permissions control**.
⚠️ **Cons of Manifest V3**
- **Service workers expire when idle** (requires event-driven coding).
- **Less flexible network request modification**.
- **No inline scripts or styles** (requires workarounds).
---
## **Final Thoughts**
- **New extensions must use MV3** (MV2 is no longer supported in Chrome Web Store).
- Existing MV2 extensions **will stop working by June 2025**.
- If your extension uses **persistent background scripts, blocking `webRequest`, or inline scripts**, you **must migrate**.